/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package stub;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;

/**
 *
 * @author nacho
 */
public class Stub implements StubInterface {
    URL urlServidor;

    public Stub(URL servidor) {
        //net.setUrlServidor(servidor);
        urlServidor = servidor;
    }


    public int rfsOpen(String filename, boolean modo) throws ConnectionException, FileFoundException, IllegalAccessException, FileNotFoundException,IOException {
        Socket socket = new Socket(urlServidor.getHost(), urlServidor.getPort());


        Mensaje respuesta;
        Mensaje open = Protocolo.getInstance().empaquetar(Protocolo.RFS_OPEN, modo, filename);
        try {
        //net.send(open); //de la clase Network
        send(socket, open);
        //respuesta = net.receive();
        respuesta = receive(socket);
        int codOp = Protocolo.getInstance().desempaquetarCodOp(respuesta);
        
        if (codOp == Protocolo.RFS_OPEN) {
            int status = Protocolo.getInstance().desempaquetarStatus(respuesta);
            if (status == Protocolo.OK) {
                //net.close();
                return Protocolo.getInstance().desempaquetarArchivo(respuesta);
            } else {
               tratarError(status);
            }
        } else {
            tratarError(Protocolo.OPERATION_ERROR);
        }
        } catch (ConnectException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        catch (OperationException ex){
        	System.err.println("#####################");
        	System.err.println(ex.getMessage());
        	System.err.println("####################");
        } catch (SocketException ex) {
            throw new ConnectionException("El servidor se ha desconectado");
        } catch (IOException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        finally{
            socket.close();
        }
        return 0;
    }

    public Data rfsRead(int fd,String filename) throws ConnectionException, FileFoundException, IllegalAccessException, FileNotFoundException, IOException{
        Socket socket = new Socket(urlServidor.getHost(), urlServidor.getPort());

        Mensaje respuesta;
        Mensaje read = Protocolo.getInstance().empaquetar(Protocolo.RFS_READ, fd, filename);
        try {
        //net.send(read);
        //respuesta = net.receive();
            send(socket, read);
           respuesta = receive(socket);
        int codOp = Protocolo.getInstance().desempaquetarCodOp(respuesta);
        //System.out.println("Cod operacion: " + codOp);
        
        if (codOp == Protocolo.RFS_READ) {
            int status = Protocolo.getInstance().desempaquetarStatus(respuesta);
            if (status == Protocolo.OK) {
                //System.out.println("Texto: " + new String(Protocolo.getInstance().desempaquetarData(respuesta)));
                return new Data(Protocolo.getInstance().desempaquetarLongitudData(respuesta), Protocolo.getInstance().desempaquetarData(respuesta));
            } else {
               tratarError(status);
            }
        } else {
            tratarError(Protocolo.OPERATION_ERROR);
        }
        } catch (ConnectException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        catch (OperationException ex){
        	System.err.println("#####################");
        	System.err.println(ex.getMessage());
        	System.err.println("####################");
        } catch (SocketException ex) {
            throw new ConnectionException("El servidor se ha desconectado");
        } catch (IOException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        finally{
            socket.close();
        }
        return null;
    }

    public void rfsWrite(int fd,String filename, byte[] stream,int longitud) throws ConnectionException, FileFoundException, IllegalAccessException, FileNotFoundException, IOException {
    Socket socket = new Socket(urlServidor.getHost(), urlServidor.getPort());

        Mensaje respuesta;
        
        Mensaje write = Protocolo.getInstance().empaquetar(Protocolo.RFS_WRITE,filename ,fd, stream,longitud);
        try {
//        net.send(write);
//        respuesta = net.receive();
            send(socket, write);
            respuesta = receive(socket);
        int codOp = Protocolo.getInstance().desempaquetarCodOp(respuesta);
        
        if (codOp == Protocolo.RFS_WRITE) {
            int status = Protocolo.getInstance().desempaquetarStatus(respuesta);
            if (status != Protocolo.OK) {
               tratarError(status);
            }
        } else {
            tratarError(Protocolo.OPERATION_ERROR);
        }
        } catch (ConnectException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        catch (OperationException ex){
        	System.err.println("#####################");
        	System.err.println(ex.getMessage());
        	System.err.println("####################");
        } catch (SocketException ex) {
            throw new ConnectionException("El servidor se ha desconectado");
        } catch (IOException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        finally{
            socket.close();
        }
    }

    public void rfsClose(int fd,String filename) throws ConnectionException, FileFoundException, IllegalAccessException, FileNotFoundException, IOException {
Socket socket = new Socket(urlServidor.getHost(), urlServidor.getPort());
        Mensaje respuesta;
        Mensaje close = Protocolo.getInstance().empaquetar(Protocolo.RFS_CLOSE, fd,filename);
        try {
        //        net.send(write);
//        respuesta = net.receive();
            send(socket, close);
            respuesta = receive(socket);
        int codOp = Protocolo.getInstance().desempaquetarCodOp(respuesta);
        
        if (codOp == Protocolo.RFS_CLOSE) {
            int status = Protocolo.getInstance().desempaquetarStatus(respuesta);
            if (status != Protocolo.OK) {
               tratarError(status);
            }
        } else {
            tratarError(Protocolo.OPERATION_ERROR);
        }
        } catch (ConnectException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
    catch (OperationException ex){
    	System.err.println("#####################");
    	System.err.println(ex.getMessage());
    	System.err.println("####################");
    } catch (SocketException ex) {
            throw new ConnectionException("El servidor se ha desconectado");
        } catch (IOException ex) {
            throw new ConnectionException("Error de Entrada / Salida " + ex.getMessage());
        }
        finally{
            socket.close();
        }
    }

    private void tratarError(int error) throws ConnectionException, FileFoundException, IllegalAccessException, FileNotFoundException, OperationException {
        switch (error) {
            case Protocolo.ACCESS_DENIED:
                throw new IllegalAccessException("Acceso denegado");
            case Protocolo.CONECTION_FAILED:
                throw new ConnectionException("Falló la conexión");
            case Protocolo.FILE_FOUND:
                throw new FileFoundException();
            case Protocolo.FILE_NOT_FOUND:
                throw new FileNotFoundException("El archivo no existe");
            case Protocolo.OPERATION_ERROR:
                throw new OperationException("Error en la operación");
        }
    }

     private void send(Socket socket,Mensaje mensaje) throws ConnectException {
        try {

                // preparo todo para el envio del mensaje
                ObjectOutputStream flujo = new ObjectOutputStream(socket.getOutputStream());

                flujo.flush();
                flujo.writeObject(mensaje);
                flujo.flush();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

     public Mensaje receive(Socket socket) throws SocketException, IOException {
        Mensaje mensaje = new Mensaje();

            try {
                // preparo todo para la recepcion del mensaje
                    ObjectInputStream flujo = new ObjectInputStream(socket.getInputStream());

                // recibo el mensaje
                mensaje = (Mensaje) flujo.readObject();
                // entrego el mensaje
                return mensaje;

            }
        catch (ClassNotFoundException ex) {
                System.err.println("#####################\n");
                System.err.println(ex.getMessage());
                ex.printStackTrace();
                System.err.println("#####################\n");

                return null;
            }

    }

}
